//
//  HBDownloadManager.m
//  downloadTest
//
//  Created by Rambo on 2019/1/12.
//  Copyright © 2019 HB. All rights reserved.
//

#import "HBDownloadManager.h"
#import <AVKit/AVKit.h>
#import <CommonCrypto/CommonDigest.h>

static NSInteger const kMaxQueue = 6;

@interface HBDownloadManager ()

@property (nonatomic, strong) NSMutableDictionary *downloadStore;   ///< 存储下载的block  key:url

@property (nonatomic, strong) NSCache *imageCache;  ///< 内存缓存图片

@property (nonatomic, strong) NSOperationQueue *operationQueue;     ///< 线程管理

@property (nonatomic, strong) NSMutableArray *downloading;  ///< 正在下载的链接

@property (nonatomic, strong) NSMutableArray *downloadQueue;        ///< 排队下载的链接

//@property (nonatomic, strong) NSMutableDictionary *downloadCompleteQueue;
@end

@implementation HBDownloadManager

+ (instancetype)manager{
    static dispatch_once_t onceToken;
    static HBDownloadManager *manager;
    dispatch_once(&onceToken, ^{
        if (manager == nil) {
            manager = [[self alloc] init];
            [[NSNotificationCenter defaultCenter] addObserver:manager selector:@selector(memoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
        }
    });
    return manager;
}

- (void)downloadVideoFirseFrameWithurl:(NSString*)url complete:(HBDownloadManagerImageBlock)complete{
//    NSLog(@"当前线程数量----%zd",self.operationQueue.operationCount);
    if (url == nil) return;
    NSString *key = [self md5String:url];
    if ([self.imageCache objectForKey:key]) {
        !complete ? : complete([self.imageCache objectForKey:key]);
        return;
    }
    
    if ([self getLocalImageForUrl:url]) {
        !complete ? : complete([self getLocalImageForUrl:url]);
        return;
    }
    
    NSMutableArray *blockStore = self.downloadStore[url];
    if (blockStore == nil) {
        blockStore = [NSMutableArray array];
        self.downloadStore[url] = blockStore;
    }
    if (complete && ![blockStore containsObject:complete]) {
        [blockStore addObject:complete];
    }
    
    if ([self.downloading containsObject:url]) return;
    
    if (self.operationQueue.operationCount >= kMaxQueue) {
        [self.downloadQueue insertObject:url atIndex:0];
        NSMutableArray *blockStore_temp = self.downloadStore[url];
        if (blockStore_temp == nil) {
            blockStore_temp = [NSMutableArray array];
            self.downloadStore[url] = blockStore_temp;
        }
        if (complete && ![blockStore_temp containsObject:complete]) {
            [blockStore_temp addObject:complete];
        }
        return;
    }
    [self.downloading addObject:url];
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:url];
    [self.operationQueue addOperation:operation];

}

- (void)downloadImage:(NSString*)url{
//    NSLog(@"下载线程%@---%zd", [NSThread currentThread], self.operationQueue.operationCount);
    //    // 获取视频第一帧
    NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:url] options:opts];
    AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset];
    generator.appliesPreferredTrackTransform = YES;
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    generator.maximumSize = CGSizeMake(screenSize.width, screenSize.width);
    NSError *error = nil;
    CGImageRef img = [generator copyCGImageAtTime:CMTimeMake(0, 10) actualTime:NULL error:&error];
    if (error) {
//        NSLog(@"error---%@--%zd",error.localizedDescription, error.code);
    }
    UIImage *image = [UIImage imageWithCGImage:img];
    CGImageRelease(img);
    dispatch_async(dispatch_get_main_queue(), ^{
        //保存图片到沙盒中
        [self saveImageInLocalWithUrl:url image:image];
        if ([self.downloading containsObject:url]) {
            [self.downloading removeObject:url];
        }
        NSMutableArray *blockStore = self.downloadStore[url];
        for (NSInteger index = 0; index < blockStore.count; index++) {
            HBDownloadManagerImageBlock block = blockStore[index];
            !block ? : block(image);
        }
        self.downloadStore[url] = nil;
        NSString *firstUrl = self.downloadQueue.firstObject;
        if (firstUrl) {
            [self.downloadQueue removeObjectAtIndex:0];
            [self downloadVideoFirseFrameWithurl:firstUrl complete:nil];
        }
    });
    
}

- (NSString*)getLocalImageFilePath{
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    path = [path stringByAppendingPathComponent:@"HBVideoFirstFrema"];
    NSFileManager *fileManeger = [NSFileManager defaultManager];
    
    if (![fileManeger fileExistsAtPath:path]) {
        [fileManeger createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
    }
    return path;
}

- (void)saveImageInLocalWithUrl:(NSString*)url image:(UIImage*)image{
    if (image == nil || url == nil) return;
    NSString *localPath = [self getLocalImageFilePath];
    NSString *key = [self md5String:url];
    NSString *imagePaht = [localPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png",key]];
    BOOL result = [UIImagePNGRepresentation(image) writeToFile:imagePaht atomically:YES];
//    NSLog(@"%d",result);
    [self.imageCache setObject:image forKey:key];
}

- (UIImage*)getLocalImageForUrl:(NSString*)url{
    NSString *localPath = [self getLocalImageFilePath];
    NSString *key = [self md5String:url];
    NSString *imagePaht = [localPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png",key]];
    UIImage *image = [UIImage imageWithContentsOfFile:imagePaht];
    if (image) {
        [self.imageCache setObject:image forKey:key];
    }
    return image;
}

- (NSString *)md5String:(NSString *)str;
{
    const char *cStr = [str UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (uint32_t)strlen(cStr), result);
    return [NSString stringWithFormat:
            @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]
            ];
    
}

#pragma mark - 通知

- (void)memoryWarning{
    [self.imageCache removeAllObjects];
}

#pragma mark - 懒加载

- (NSMutableDictionary *)downloadStore{
    if (!_downloadStore) {
        _downloadStore = [NSMutableDictionary dictionary];
    }
    return _downloadStore;
}


- (NSCache *)imageCache{
    if (!_imageCache) {
        _imageCache = [[NSCache alloc] init];
        _imageCache.totalCostLimit = 20;
    }
    return _imageCache;
}

- (NSOperationQueue *)operationQueue{
    if (!_operationQueue) {
        _operationQueue = [[NSOperationQueue alloc] init];
        _operationQueue.maxConcurrentOperationCount = kMaxQueue;
    }
    return _operationQueue;
}

- (NSMutableArray *)downloading{
    if (!_downloading) {
        _downloading = [NSMutableArray array];
    }
    return _downloading;
}

- (NSMutableArray *)downloadQueue{
    if (!_downloadQueue) {
        _downloadQueue = [NSMutableArray array];
    }
    return _downloadQueue;
}



@end
